package cbs.demo;

import cbs.demo.anno.DemoAnnotation;
import io.quarkus.gizmo.ClassCreator;
import io.quarkus.gizmo.FieldDescriptor;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;

import static io.quarkus.gizmo.MethodDescriptor.ofMethod;

/**
 * Hello world!
 */
public class App {
    public static void main(String[] args) {
        //创建类
        try (var creator = new ClassCreator((name, data) -> {
            var path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
            System.out.println("输出路径:" + path);
            //文件输出流输出生成的class文件
            try (OutputStream os = Files.newOutputStream(Path.of(path + "/" + name + ".class"))) {
                //class文件输出到maven的target/classes
                os.write(data);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, "cbs/demo/MyClass", null, Object.class.getName())) {
            creator.addAnnotation(DemoAnnotation.class);
            //创建方法,方法名:method
            var methodCreator = creator.getMethodCreator("method", void.class);
            //方法体输出:hello gizmo啊
            methodCreator.invokeVirtualMethod(
                    ofMethod(PrintStream.class, "println", void.class, String.class),
                    methodCreator.readStaticField(FieldDescriptor.of(System.class, "out", PrintStream.class)),
                    methodCreator.load("hello gizmo啊"));
            //无返回值
            var tryBlock = methodCreator.tryBlock();
            tryBlock.invokeVirtualMethod(
                    ofMethod(PrintStream.class, "println", void.class, String.class),
                    tryBlock.readStaticField(FieldDescriptor.of(System.class, "out", PrintStream.class)),
                    tryBlock.load("我在try块中"));
            tryBlock.addCatch(IllegalStateException.class);
            tryBlock.close();

            methodCreator.returnValue(null);
            methodCreator.close();
        }
        try {
            //使用生成的class
            var clazz = Class.forName("cbs.demo.MyClass");
            System.out.println(clazz.getName());

            var demoAnnotation = clazz.getAnnotation(DemoAnnotation.class);
            var val = demoAnnotation.value();
            System.out.println(val);

            var instance = clazz.getDeclaredConstructor().newInstance();
            var m = clazz.getMethod("method");
            m.invoke(instance);
        } catch (ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
